Array.prototype.sum = function(){
    var acc = 0
    for(var i = 0; i<this.length; i++){
        acc += this[i]
    }
    return acc
}

Array.prototype.min = function(){
    return Math.min.apply(null, this)
}

Array.prototype.map = function(cback){
    var result = new Array()
    for(var i = 0; i<this.length; i++){
        result.push(cback(this[i]))
    }
    return result
}

Array.prototype.grep = function(cback){
    var result = new Array()
    for(var i = 0; i<this.length; i++){
        if(cback(this[i])){
            result.push(this[i])
        }
    }
    return result
}

Array.prototype.unique = function() {
    var isEqual = function(f, s){
        var nrKeys = function(a) {
            var i = 0;
            for (key in a) {
                i++;
            }
            return i;
        }
        var compareAssociativeArrays = function(a, b) {
            if (a == b) {
                return true;
            }   
            if (nrKeys(a) != nrKeys(b)) {
                return false;
            }
            for (key in a) {     
                if (a[key] != b[key]) {
                    return false;
                }
            }
            return true;
        }
        return compareAssociativeArrays(f, s)
    }
    var a = [];
    var l = this.length;
    for(var i=0; i<l; i++) {
        for(var j=i+1; j<l; j++) {
            // If this[i] is found later in the array
            if (isEqual(this[i], this[j]))
                j = ++i;
        }
        a.push(this[i]);
    }
    return a;
}

Array.prototype.subList = function(min, max){
    var res = new Array()
    for(var i = min; i <= max; i++){
        res.push(this[i])
    }
    return res
}

function checaCortes(maximum, elements, poss){
    var inner = function(max, cortes, possibilidade, i){
        var aux = new Array()
        if(possibilidade.sum() > max) return aux
        aux = aux.concat(possibilidade)
        var sum = (possibilidade.length != 0)?possibilidade.sum():0
        while(sum < max){
            if((sum + cortes[i]) <= max){
                aux.push(cortes[i])	
            } 
            sum += cortes[i]
        }
        return aux.sort()
    }
    var result = new Array()
    for(var i = 0; i < cortes.length; i++){
        result.push(inner(maximum, elements, poss, i))
    }
    return result
}

function geraPossibilidades(max, cortes){
    var possibilidades = new Array()
    var aux = function(a){
        return checaCortes(max, cortes, a)
    }
    for(var i = 0; i < cortes.length; i++){
        for(var j = 0; j < cortes.length; j++){
            var inc = new Array()
            for(var k = 0; k < j+1; k++){
                inc.push(cortes[i])
            }
            var vals = [inc, cortes.subList(i,j)].map(function(el){
                return aux(el)
            })
            for(var k = 0; k < vals.length; k++){
                possibilidades = possibilidades.concat(vals[k].sort(function(a, b){
                    return b - a
                }))
            }
        }
    }
    return possibilidades.unique().grep(function(el){
        return el.sum() > max - cortes.min()
    })
}

max = 15
cortes = [5, 4, 3]

var res = geraPossibilidades(max, cortes)

for(var i = 0; i< res.length; i++){
    console.log(res[i] + " => " + res[i].sum())
}